package cn.edu.usst.cs.stu_sys011;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.jetbrains.annotations.NotNull;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import static cn.edu.usst.cs.stu_sys011.StuInfo.*;

@WebServlet(name = "helloServlet", value = "/hello-servlet")
public class HelloServlet extends HttpServlet {

    public static String ATTR_TYPE = "stuInfoList";
    public static String NEW_STU = "new_student";
    private static final String PROCESSED_KEY = "successfully_processed";

    private Map<Long, StuInfo> stuInfoMap;
    private Map<String, GF_Field> fieldMap;
    String DELETE="delete";

    public void init() {
        stuInfoMap = new HashMap<>();
        fieldMap = new HashMap<>();
        fieldMap.put(MARK_ROUTINE, GF_Field.MARK_ROUTINE);
        fieldMap.put(MARK_FINAL, GF_Field.MARK_FINAL);
        fieldMap.put(DELETE,GF_Field.DELETE);
    }

    public void doGet(@NotNull HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        Set<StuInfo> info_now = new LinkedHashSet<>(stuInfoMap.values());
        request.setAttribute(ATTR_TYPE, info_now);
        request.getRequestDispatcher("js_main.jsp").forward(request, response);
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        Exception exception=null;
        System.out.println("doPost");
        JSONObject json;
        StringBuilder builder = new StringBuilder();
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("utf-8");
        try (InputStream inputStream = request.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
            while (true) {
                String line = reader.readLine();
                if (line == null) break;
                builder.append(line);
            }
        }
        PROCESS:
        {
            JSON:
            {
                try {
                    json = new JSONObject(builder.toString());
                } catch (JSONException jsonException) {
                    exception = jsonException;
                    break JSON;
                }
                try {
                    processStuAddition(json);
                    break PROCESS;
                } catch (IllegalArgumentException e) {
                    exception = e;
                }
                try {
                    deleteStudent(json);
                    break PROCESS;
                } catch (Exception e) {
                    exception = e;
                }
            }
            try {
                updateMarks(builder.toString().split("&"));

            } catch (RuntimeException e) {
                exception = e;
            }
        }

        if (exception == null) return;
        request.setAttribute(ATTR_TYPE, new LinkedHashSet<>(stuInfoMap.values()));
        request.setAttribute(PROCESSED_KEY, false);
        request.setAttribute("message", "无效数据包");
        request.getRequestDispatcher("js_main.jsp").forward(request, response);
    }

    public void processStuAddition(JSONObject json) throws JSONException {
        String update_type = json.getString("update_type");
        if (update_type == null) {
            throw new IllegalArgumentException("录入失败：数据包格式错误");
        }
        long ID;
        try {
            ID = Long.parseLong(json.getString(STU_ID));
        } catch (NumberFormatException e) {
            throw new NumberFormatException("请检查学号是否为纯数字");
        }
        String name = json.getString(StuInfo.NAME);
        String major = json.getString(MAJOR);
        StuInfo info = new StuInfo(name, ID, major, new Grade());
        if (stuInfoMap.containsKey(ID)) {
            throw new IllegalArgumentException("该生信息已存在");
        }
        stuInfoMap.put(ID, info);
    }

    public void updateMarks(String[] params) {
        READ:
        {
            for (String param : params) {
                String[] pairs = param.split("=");
                if (pairs.length != 2) {
                    break READ;
                }
                float value = Float.parseFloat(pairs[1]);
                String[] update_object = pairs[0].split("__");
                if (update_object.length != 2) {
                    break READ;
                }
                long ID = Long.parseLong(update_object[1]);
                StuInfo info = stuInfoMap.get(ID);
                GF_Field field = fieldMap.get(update_object[0]);
                if (info == null) {
                    break READ;
                }
                if (field == null) {
                    break READ;
                }
                updateMark(info, field, value);
            }
            return;
        }
        throw new IllegalArgumentException();
    }

    public void updateMark(StuInfo stu, GF_Field field, float value) {
        long id=stu.stu_id();
        switch (field) {
            case MARK_ROUTINE:
                stu.grade().setGrade_routine(value);
                break;
            case MARK_FINAL:
                stu.grade().setGrade_final(value);
                break;
            case DELETE:
                fieldMap.remove(id);
                break;
            default:
                break;
        }
    }

    public void deleteStudent(JSONObject object) throws JSONException {
        long stu_id = object.getLong("stu_id");
        stuInfoMap.remove(stu_id);
    }

    public void destroy() {
    }

    public enum GF_Field {
        MARK_ROUTINE, MARK_FINAL,DELETE
    }

}



